/**
 * SPI0 info:
    - SPI0_SCK: GPIO2_25(Pin 89, wPi 14), number 23
    - SPI0_MISO: GPIO2_28(Pin 92, wPi 12), number 21
    - SPI0_MOSI:GPIO2_27(Pin 91, wPi 11), number 19
    - SPI0_CS: GPIO2_26(Pin 90, wPi 15), number 24
    - linux device: /dev/spidev0.0
 */

#include <cstring>
#include <cstdio>
#include <stdint.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include "wiringPiSPIFix.h"


static void hex_dump(const unsigned char *src, size_t length, size_t line_size, char *prefix)
{
	int i = 0;
	const unsigned char *address = src;
	const unsigned char *line = address;
	unsigned char c;

	printf("%s | ", prefix);
	while (length-- > 0) {
		printf("%02X ", *address++);
		if (!(++i % line_size) || (length == 0 && i % line_size)) {
			if (length == 0) {
				while (i++ % line_size)
					printf("__ ");
			}
			printf(" |");
			while (line < address) {
				c = *line++;
				printf("%c", (c < 32 || c > 126) ? '.' : c);
			}
			printf("|\n");
			if (length > 0)
				printf("%s | ", prefix);
		}
	}
}


int main(){
    // init spi
    int ret = -1;
    /**
     * SPI_CPOL: 
     * 时钟空闲idle时候的电平是高电平，所以当SCLK有效的时候，就是低电平
     * 
     * CPHA=0，表示第一个边沿：
     * 对于CPOL=0，idle时候的是低电平，第一个边沿就是从低变到高，所以是上升沿；
     * 对于CPOL=1，idle时候的是高电平，第一个边沿就是从高变到低，所以是下降沿；
     * 
     * CPHA=1，表示第二个边沿：
     * 对于CPOL=0，idle时候的是低电平，第二个边沿就是从高变到低，所以是下降沿；
     * 对于CPOL=1，idle时候的是高电平，第一个边沿就是从低变到高，所以是上升沿；
     */
    //uint32_t mode = SPI_CPOL | SPI_CPHA;
    //uint32_t mode = SPI_NO_CS;
    uint32_t mode = 0;

    ret = wiringPiSPISetupMode (0, 0, 1000 * 1000, mode);
    if(ret < 0){
        printf("Spi init failed\n");
        return -1;
    }

    // data buffer
    unsigned char txBuffer[8], rxBuffer[8];

    // init send buffer cache, and clean rxbuffer
    memset(txBuffer, 100, sizeof(txBuffer));
    memset(rxBuffer, 0, sizeof(rxBuffer));

    char prefix[8] = "RX";
    while (1){
        // send
        ret = wiringPiSPIDataRW(0, txBuffer, rxBuffer, 8);
        if(ret < 0){
            printf("Spi data read failed\n");
            return -1;
        }

        // print recv
        hex_dump(rxBuffer, 8, 32, prefix);

        // sleep
        // sleep(1);
        //usleep(50);
        break;
    }
}